﻿using BootyBay.PrivateStoreApp.AgentServicesRef;
using BootyBay.PrivateStoreApp.Common;
using BootyBay.PrivateStoreApp.DataModel;
using BootyBay.PrivateStoreApp.StoreServicesRef;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.UI.Notifications;
using Windows.UI.Popups;
using Windows.UI.Xaml;

namespace BootyBay.PrivateStoreApp.ViewModels
{
    public class AppDetailPageVM : BindableBase
    {
        #region Instance
        private static AppDetailPageVM instance = null;
        public static AppDetailPageVM Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = new AppDetailPageVM();
                }
                return instance;
            }
        }

        #endregion

        public AppDetailPageVM()
        {
            svcClient = new StoreServicesClient();
            agentClient = new AgentSvcClient();

            RequestInstallationCommand = new RelayCommand(() =>
            {
                RequestAppAction();//单击安装或运行按钮时执行
            });
        }

        #region 对象声明

        StoreServicesClient svcClient;
        AgentSvcClient agentClient;
        private Guid TaskIDFortheAppOpt;
        private DispatcherTimer statusRefreshTimer;
        bool isRefreshing = false;
        private ObservableCollection<string> m_InstallrefreshData = new ObservableCollection<string>();

        public ObservableCollection<string> InstallrefreshData
        {
            get { return m_InstallrefreshData; }
            set { SetProperty(ref m_InstallrefreshData, value); }
        }
        private ObservableCollection<string> m_UnInstallrefreshData = new ObservableCollection<string>();

        public ObservableCollection<string> UnInstallrefreshData
        {
            get { return m_UnInstallrefreshData; }
            set { SetProperty(ref m_UnInstallrefreshData, value); }
        }

        private List<string> m_DownLoadApps = new List<string>();

        public List<string> DownLoadApps
        {
            get
            {
                return m_DownLoadApps;
            }
            set
            {
                SetProperty(ref m_DownLoadApps, value);
            }
        }


        private bool isLoading = false;
        public bool IsLoading
        {
            get
            {
                return isLoading;
            }
            set
            {
                SetProperty(ref isLoading, value);
            }

        }
        private bool isInstallOk = false;
        public bool IsInstallOk
        {
            get
            {
                return isInstallOk;
            }
            set
            {
                SetProperty(ref isInstallOk, value);
            }

        }

        private bool isActionRequired = false;
        public bool IsActionRequired
        {
            get
            {
                return isActionRequired;
            }
            set
            {
                SetProperty(ref isActionRequired, value);
            }
        }

        private string actionName = "Install";
        public string ActionName
        {
            get
            {
                return actionName;
            }
            set
            {
                SetProperty(ref actionName, value);
            }
        }

        private string noteContent = "";
        public string NoteContent
        {
            get
            {
                return noteContent;
            }
            set
            {
                SetProperty(ref noteContent, value);
            }
        }

        public RelayCommand RequestInstallationCommand { private set; get; }
        public RelayCommand RequestInstallationCommand2 { private set; get; }

        private UserAppDataModel appModel;

        public UserAppDataModel AppModel
        {
            get
            {
                return appModel;
            }
            set
            {
                SetProperty(ref appModel, value);
            }
        }

        private UserAppDataModel relateAppModel;

        public UserAppDataModel RelateAppModel
        {
            get
            {
                return relateAppModel;
            }
            set
            {
                SetProperty(ref relateAppModel, value);
            }
        }

        #endregion

        #region 查询当前应用数据
        public async Task LoadAppData(UserAppDataModel appDataModel)
        {
            this.AppModel = appDataModel;
            var mgmtTask = await agentClient.GetTaskStatusAsync(TaskIDFortheAppOpt);

            if (mgmtTask != null)
            {
                this.AppModel.OptStatus = mgmtTask.OptStatus;
                this.AppModel.OptType = mgmtTask.OptType;

            }
            await LoadAppLocalStatusFromAgent();
        }
        #endregion

        #region 应用安装成功弹出Toast通知
        public async void CreatTostNotification(string appName)
        {
            var notifier = ToastNotificationManager.CreateToastNotifier();

            // Make sure notifications are enabled
            if (notifier.Setting != NotificationSetting.Enabled)
            {
                var dialog = new MessageDialog("Notifications are currently disabled");
                await dialog.ShowAsync();
                return;
            }

            // Get a toast template and insert a text node containing a message
            var template = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText01);
            var element = template.GetElementsByTagName("text")[0];
            element.AppendChild(template.CreateTextNode(appName + " 应用安装成功!"));

            // Schedule the toast to appear 5 seconds from now
            var date = DateTimeOffset.Now.AddSeconds(1);
            var stn = new ScheduledToastNotification(template, date);
            notifier.AddToSchedule(stn);
        }
        #endregion

        #region 根据应用状态查询应用的列表
        /// <summary>
        /// 根据应用状态查询应用的列表
        /// </summary>
        /// <param name="appLocalStatus">应用状态</param>
        /// <param name="YesOrNo">true：根据当前状态查询应用列表；false：查询除了当前状态的所有状态的应用列表</param>
        /// <returns></returns>
        public async Task<AppListPageVM> GetAppsInfoByStatus(AppLocalStatus appLocalStatus, bool YesOrNo)
        {
            AppListPageVM yourAppsPageVM = new AppListPageVM();
            foreach (var item in AppListPageVM.Instance.AppData)
            {
                StoreAppMgmtTask mgmtTask = new StoreAppMgmtTask()
                {
                    // - Ranger the packageName is the actually the Identity, instead of app name.
                    AppInfoID = item.AppView.Id,
                    AppPackageName = item.AppView.IdentityName, //item.AppView.ApplicationName,
                    AppPublisherName = item.AppView.Publisher,
                    AppVerInfoID = item.AppView.Id_ApplicationVersion,
                    AppVersion = item.AppView.Version,
                    UserName = App.CurrentUserName,
                    UtcTimeStamp = DateTime.UtcNow,
                    OptType = AppOperationType.GetLocalStatus,
                };

                var localStatus = AppLocalStatus.Unknown;
                bool isShow = false;
                try
                {
                    localStatus = await agentClient.GetAppLocalStatusAsync(mgmtTask);
                }
                catch (System.ServiceModel.EndpointNotFoundException ex)
                {
                    isShow = true;
                }
                if (isShow)
                {
                    var messageDialog = new MessageDialog("请先启动AgentSvcClient服务！");
                    await messageDialog.ShowAsync();
                    break;
                }
                else
                {
                    if (YesOrNo)
                    {
                        if (localStatus == appLocalStatus)
                        {
                            UserAppDataModel userModel = new UserAppDataModel(item.AppView);
                            userModel.LocalStatus = localStatus;
                            yourAppsPageVM.AppData.Add(userModel);
                        }
                    }
                    else
                    {
                        if (localStatus != appLocalStatus)
                        {
                            UserAppDataModel userModel = new UserAppDataModel(item.AppView);
                            userModel.LocalStatus = localStatus;
                            yourAppsPageVM.AppData.Add(userModel);
                        }
                    }
                }
            }
            return yourAppsPageVM;
        }
        #endregion

        #region 运行/安装应用
        private async Task RequestAppAction()
        {
            bool bo = await GetValidateUser();
            if (bo)
            {
                if (this.AppModel.LocalStatus == AppLocalStatus.Installed)
                {
                    RequestForAppRunning();
                }
                else
                {
                    RequestForAppInstallation();
                }
            }
        }
        private async void RequestForAppRunning()
        {
            if (string.IsNullOrEmpty(this.AppModel.AppView.ProtocolUrl))
            {
                MessageDialog msg = new MessageDialog("No protocol associated to the app.", "Please run the app from Windows Start Screen");
                await msg.ShowAsync();

                //TODO: Research for a
            }
            else
            {
                string url = this.AppModel.AppView.ProtocolUrl;
                if (!url.Contains(":"))
                {
                    url = url + ":";
                    // like showcasedemo:    
                    //slashs are not required.
                }

                Uri protocolUri = new Uri(url);

                try
                {
                    await Windows.System.Launcher.LaunchUriAsync(protocolUri);
                }
                catch
                {
                    MessageDialog msg = new MessageDialog("App launch failed.", "Meeting some problem.");
                    msg.ShowAsync();
                }
            }
        }

        private async void RequestForAppInstallation()
        {

            //this.AppModel.LocalStatus = AppLocalStatus.Processing;
            this.IsLoading = true;
            RefreshStatusProperties();

            var appPkgInfo = await svcClient.GetPackageUrlAsync(AppModel.AppView.Id_ApplicationVersion, (int)App.CurrentPackageArchitecture);

            if (appPkgInfo == null)
            {
                await LoadAppLocalStatusFromAgent();
                return;
                //TODO, add notification
            }


            StoreAppMgmtTask mgmtTask = new StoreAppMgmtTask()
            {
                AppInfoID = AppModel.AppView.Id,
                AppPackageName = AppModel.AppView.IdentityName,
                AppPublisherName = AppModel.AppView.Publisher,
                AppVerInfoID = AppModel.AppView.Id_ApplicationVersion,
                AppVersion = AppModel.AppView.Version,
                UserName = App.CurrentUserName,
                UtcTimeStamp = DateTime.UtcNow,
                OptType = AppOperationType.Install,
                PackageCertLocationUrl = appPkgInfo.PackageCertLocationUrl,
                PackageLocationUrl = appPkgInfo.PackageLocationUrl
            };


            var optGuid = await agentClient.SubmitClientAppOperationRequestAsync(mgmtTask);
            var mgmtTasks = await agentClient.GetTaskStatusAsync(optGuid);

            this.TaskIDFortheAppOpt = optGuid;

            statusRefreshTimer = new DispatcherTimer();
            statusRefreshTimer.Interval = TimeSpan.FromSeconds(5);
            statusRefreshTimer.Tick -= statusRefreshTimer_Tick;
            statusRefreshTimer.Tick += statusRefreshTimer_Tick;
            statusRefreshTimer.Start();

            this.IsLoading = false;
        }
        #endregion

        #region 卸载应用
        public async Task<Guid> RequestForAppUnInstallation(UserAppDataModel userAppDataModel)
        {
            userAppDataModel.OptType = AppOperationType.Uninstall;
            StoreAppMgmtTask mgmtTask = new StoreAppMgmtTask()
            {
                AppInfoID = userAppDataModel.AppView.Id,
                AppPackageName = userAppDataModel.AppView.IdentityName,
                AppPublisherName = userAppDataModel.AppView.Publisher,
                AppVerInfoID = userAppDataModel.AppView.Id_ApplicationVersion,
                AppVersion = userAppDataModel.AppView.Version,
                UserName = App.CurrentUserName,
                UtcTimeStamp = DateTime.UtcNow,
                OptType = AppOperationType.Uninstall,
            };

            var optGuid = await agentClient.SubmitClientAppOperationRequestAsync(mgmtTask);
            this.TaskIDFortheAppOpt = optGuid;
            return optGuid;
        }
        #endregion

        #region 获取应用状态
        public async Task<AppLocalStatus> GetAppLocalStatus(UserAppDataModel userAppDataModel)
        {
            StoreAppMgmtTask mgmtTask = new StoreAppMgmtTask()
            {
                AppInfoID = userAppDataModel.AppView.Id,
                AppPackageName = userAppDataModel.AppView.IdentityName,
                AppPublisherName = userAppDataModel.AppView.Publisher,
                AppVerInfoID = userAppDataModel.AppView.Id_ApplicationVersion,
                AppVersion = userAppDataModel.AppView.Version,
                UserName = App.CurrentUserName,
                UtcTimeStamp = DateTime.UtcNow,
                OptType = AppOperationType.GetLocalStatus,
            };

            var localStatus = await agentClient.GetAppLocalStatusAsync(mgmtTask);
            return localStatus;
        }

        private async Task LoadAppLocalStatusFromAgent()
        {
            StoreAppMgmtTask mgmtTask = new StoreAppMgmtTask()
            {
                AppInfoID = AppModel.AppView.Id,
                AppPackageName = AppModel.AppView.IdentityName,
                AppPublisherName = AppModel.AppView.Publisher,
                AppVerInfoID = AppModel.AppView.Id_ApplicationVersion,
                AppVersion = AppModel.AppView.Version,
                UserName = App.CurrentUserName,
                UtcTimeStamp = DateTime.UtcNow,
                OptType = AppOperationType.GetLocalStatus,
            };

            var localStatus = await agentClient.GetAppLocalStatusAsync(mgmtTask);

            this.AppModel.LocalStatus = localStatus;

            RefreshStatusProperties();
        }

        private void RefreshStatusProperties()
        {
            switch (this.AppModel.LocalStatus)
            {
                case AppLocalStatus.Installed:
                    IsActionRequired = true;
                    ActionName = "Run";
                    NoteContent = "This app is installed on this PC.";
                    break;
                case AppLocalStatus.InStore:
                    IsActionRequired = true;
                    ActionName = "Install";
                    NoteContent = "";
                    break;
                case AppLocalStatus.OutDated:
                    IsActionRequired = true;
                    ActionName = "Update";
                    NoteContent = "";
                    break;
                case AppLocalStatus.Processing:
                    IsActionRequired = false;
                    ActionName = "Processing...";
                    NoteContent = "";
                    break;
                case AppLocalStatus.Purchased:
                    IsActionRequired = true;
                    ActionName = "Install";
                    NoteContent = "";
                    break;
                default: break;
            }
        }
        void statusRefreshTimer_Tick(object sender, object e)
        {
            RefreshMgmtTaskStatus();
        }
        private async void RefreshMgmtTaskStatus()
        {
            if (isRefreshing)
                return;

            isRefreshing = true;
            var mgmtTask = await agentClient.GetTaskStatusAsync(TaskIDFortheAppOpt);

            if (mgmtTask != null)
            {
                this.AppModel.OptStatus = mgmtTask.OptStatus;
                this.AppModel.OptType = mgmtTask.OptType;

                if (mgmtTask.OptStatus == AppOperationStatus.Succeeded)
                {
                    if (statusRefreshTimer != null)
                    {
                        statusRefreshTimer.Stop();
                        statusRefreshTimer = null;
                        IsInstallOk = true;
                    }

                    await LoadAppLocalStatusFromAgent();
                }
                else if (mgmtTask.OptStatus == AppOperationStatus.Failed)
                {
                    if (statusRefreshTimer != null)
                    {
                        statusRefreshTimer.Stop();
                        statusRefreshTimer = null;
                    }
                }
                else if (mgmtTask.OptStatus == AppOperationStatus.Unauthorized)
                {
                    if (statusRefreshTimer != null)
                    {
                        statusRefreshTimer.Stop();
                        statusRefreshTimer = null;
                    }
                }
            }
            isRefreshing = false;

        }
        #endregion

        #region 获取当前用户权限
        public async Task<bool> GetValidateUser()
        {
            View_StoreUser view_StoreUser = await svcClient.ValidateUserAsync(App.CurrentUserName);
            if (!view_StoreUser.IsValid)
            {
                MessageDialog msg = new MessageDialog("权限不足，拒绝访问!");
                await msg.ShowAsync();
            }
            return view_StoreUser.IsValid;
        }
        #endregion
    }
}
